import { Scene_Base } from "@/scenes/Scene_Base.js";
import { DataManager } from "@/managers/DataManager.js";
import { SceneManager } from "@/managers/SceneManager.js";
import { AudioManager } from "@/managers/AudioManager.js";
import { BattleManager } from "@/managers/BattleManager.js";
import { SoundManager } from "@/managers/SoundManager.js";
import { TouchInput } from "@/core/TouchInput.js";
import { Input } from "@/core/Input.js";

import { Scene_Title } from "@/scenes/Scene_Title.js";
import { Scene_Gameover } from "@/scenes/Scene_Gameover.js";
import { Scene_Battle } from "@/scenes/Scene_Battle.js";
import { Scene_Load } from "@/scenes/Scene_Load.js";

import { Spriteset_Map } from "@/containers/Spriteset_Map.js";
import { Window_Message } from "@/windows/Window_Message.js";
import { ScrollText } from "@/containers/ScrollText.js";
import { Scene_Menu } from "@/scenes/Scene_Menu.js";

import { config } from "@/managers/ConfigManager.js";

export class Scene_Map extends Scene_Base {
    constructor() {
        super();
        this._waitCount = 0;
        this._encounterEffectDuration = 0;
        this._mapLoaded = false;
        this._touchCount = 0;
    }

    create() {
        super.create();
        this._transfer = $gamePlayer.isTransferring();
        let mapId = this._transfer ? $gamePlayer.newMapId() : $gameMap.mapId();
        DataManager.loadMapData(mapId);
    }

    isReady() {
        if (!this._mapLoaded && DataManager.isMapLoaded()) {
            this.onMapLoaded();
            this._mapLoaded = true;
        }
        return this._mapLoaded && super.isReady();
    }

    onMapLoaded() {
        if (this._transfer) {
            $gamePlayer.performTransfer();
        }
        this.createDisplayObjects();
    }

    createDisplayObjects() {
        this.createSpriteset();
        //this.createMapNameWindow();
        this.createAllWindows();
    }

    createSpriteset() {
        this._spriteset = new Spriteset_Map();
        this.addChild(this._spriteset);
    }

    createMapNameWindow() {
        this._mapNameWindow = new Window_MapName();
        this.addChild(this._mapNameWindow);
    }

    createAllWindows() {
        this.createMessageWindow();
        this.createScrollTextWindow();
    }

    createMessageWindow() {
        this._messageWindow = new Window_Message(config.width,180);
        this.addWindow(this._messageWindow);
    }

    createScrollTextWindow() {
        this._scrollTextWindow = new ScrollText(config.width,config.height);
        this.addWindow(this._scrollTextWindow);
    }


    start() {
        super.start();
        SceneManager.clearStack();
        if (this._transfer) {
            this.fadeInForTransfer();
            //this._mapNameWindow.open();
            $gameMap.autoplay();
        } else if (this.needsFadeIn()) {
            this.startFadeIn(this.fadeSpeed(), false);
        }
        this.menuCalling = false;
    }

    update() {
        this.updateDestination();
        this.updateMainMultiply();
        if (this.isSceneChangeOk()) {
            this.updateScene();
        } 
        // else if (SceneManager.isNextScene(Scene_Battle)) {
        //     this.updateEncounterEffect();
        // }
        this.updateWaitCount();
        super.update();
    }

    updateMainMultiply() {
        this.updateMain();
        if (this.isFastForward()) {
            this.updateMain();
        }
    }

    updateMain() {
        let active = this.isActive();
        $gameMap.update(active);
        $gamePlayer.update(active);
        $gameTimer.update(active);
        $gameScreen.update();
    }

    isFastForward() {
        return ($gameMap.isEventRunning() && !SceneManager.isSceneChanging() &&
                (Input.isLongPressed('ok') || TouchInput.isLongPressed()));
    }

    stop() {
        super.stop();
        $gamePlayer.straighten();
        //this._mapNameWindow.close();
        if (this.needsSlowFadeOut()) {
            this.startFadeOut(this.slowFadeSpeed(), false);
        } else if (SceneManager.isNextScene(Scene_Map)) {
            this.fadeOutForTransfer();
        } else if (SceneManager.isNextScene(Scene_Battle)) {
            this.launchBattle();
        }
    }

    isBusy() {
        return ((this._messageWindow && this._messageWindow.isClosing()) ||
                this._waitCount > 0 || this._encounterEffectDuration > 0 ||
                super.isBusy(this));
    }

    terminate() {
        $gameScreen.clearZoom();
        super.terminate();
    }

    needsFadeIn() {
        return (SceneManager.isPreviousScene(Scene_Battle) ||
                SceneManager.isPreviousScene(Scene_Load));
    }

    needsSlowFadeOut() {
        return (SceneManager.isNextScene(Scene_Title) ||
                SceneManager.isNextScene(Scene_Gameover));
    }

    updateWaitCount() {
        if (this._waitCount > 0) {
            this._waitCount--;
            return true;
        }
        return false;
    }

    updateDestination() {
        if (this.isMapTouchOk()) {
            this.processMapTouch();
        } else {
            $gameTemp.clearDestination();
            this._touchCount = 0;
        }
    }

    isMapTouchOk() {
        return this.isActive() && $gamePlayer.canMove();
    }

    processMapTouch() {
        if (TouchInput.isTriggered() || this._touchCount > 0) {
            if (TouchInput.isPressed()) {
                if (this._touchCount === 0 || this._touchCount >= 15) {
                    let x = $gameMap.canvasToMapX(TouchInput.x);
                    let y = $gameMap.canvasToMapY(TouchInput.y);
                    $gameTemp.setDestination(x, y);
                }
                this._touchCount++;
            } else {
                this._touchCount = 0;
            }
        }
    }

    isSceneChangeOk() {
        return this.isActive() && !$gameMessage.isBusy();
    }

    updateScene() {
        //this.checkGameover();
        if (!SceneManager.isSceneChanging()) {
            this.updateTransferPlayer();
        }
        if (!SceneManager.isSceneChanging()) {
            this.updateEncounter();
        }
        if (!SceneManager.isSceneChanging()) {
            this.updateCallMenu();
        }
        if (!SceneManager.isSceneChanging()) {
            this.updateCallDebug();
        }
    }

    
    updateTransferPlayer() {
        if ($gamePlayer.isTransferring()) {
            SceneManager.goto(Scene_Map);
        }
    }

    updateEncounter() {
       if ($gamePlayer.executeEncounter()) {
           SceneManager.push(Scene_Battle);
       }
    }

    updateCallMenu() {
        if (this.isMenuEnabled()) {
            if (this.isMenuCalled()) {
                this.menuCalling = true;
            }
            if (this.menuCalling && !$gamePlayer.isMoving()) {
                this.callMenu();
            }
        } else {
            this.menuCalling = false;
        }
    }

    isMenuEnabled() {
        return $gameSystem.isMenuEnabled() && !$gameMap.isEventRunning();
    }

    isMenuCalled() {
        return Input.isTriggered('menu') || TouchInput.isCancelled();
    }

    callMenu() {
        SoundManager.playOk();
        SceneManager.push(Scene_Menu);
        //Window_MenuCommand.initCommandPosition();
        $gameTemp.clearDestination();
        //this._mapNameWindow.hide();
        this._waitCount = 2;
    }

    updateCallDebug() {
        if (this.isDebugCalled()) {
            SceneManager.push(Scene_Debug);
        }
    }

    isDebugCalled() {
        return Input.isTriggered('debug') && $gameTemp.isPlaytest();
    }

    fadeInForTransfer() {
        let fadeType = $gamePlayer.fadeType();
        switch (fadeType) {
        case 0: case 1:
            this.startFadeIn(this.fadeSpeed(), fadeType === 1);
            break;
        }
    }

    fadeOutForTransfer() {
        let fadeType = $gamePlayer.fadeType();
        switch (fadeType) {
        case 0: case 1:
            this.startFadeOut(this.fadeSpeed(), fadeType === 1);
            break;
        }
    }

    launchBattle() {
        BattleManager.saveBgmAndBgs();
        this.stopAudioOnBattleStart();
        SoundManager.playBattleStart();
        this.startEncounterEffect();
        this._mapNameWindow.hide();
    }

    stopAudioOnBattleStart() {
        if (!AudioManager.isCurrentBgm($gameSystem.battleBgm())) {
            AudioManager.stopBgm();
        }
        AudioManager.stopBgs();
        AudioManager.stopMe();
        AudioManager.stopSe();
    }

    startEncounterEffect() {
        this._spriteset.hideCharacters();
        this._encounterEffectDuration = this.encounterEffectSpeed();
    }

    updateEncounterEffect() {
        if (this._encounterEffectDuration > 0) {
            this._encounterEffectDuration--;
            let speed = this.encounterEffectSpeed();
            let n = speed - this._encounterEffectDuration;
            let p = n / speed;
            let q = ((p - 1) * 20 * p + 5) * p + 1;
            let zoomX = $gamePlayer.screenX();
            let zoomY = $gamePlayer.screenY() - 24;
            if (n === 2) {
                $gameScreen.setZoom(zoomX, zoomY, 1);
                this.snapForBattleBackground();
                this.startFlashForEncounter(speed / 2);
            }
            $gameScreen.setZoom(zoomX, zoomY, q);
            if (n === Math.floor(speed / 6)) {
                this.startFlashForEncounter(speed / 2);
            }
            if (n === Math.floor(speed / 2)) {
                BattleManager.playBattleBgm();
                this.startFadeOut(this.fadeSpeed());
            }
        }
    }

    snapForBattleBackground() {
        SceneManager.snapForBackground();
    }

    startFlashForEncounter(duration) {
        let color = [255, 255, 255, 255];
        $gameScreen.startFlash(color, duration);
    }

    encounterEffectSpeed() {
        return 60;
    }
}